目前還沒有畫面可以看或操作,所以單就資料流的部分先寫進資料庫,
而建立訂單目前也是先塞變數進去,所以每次都會是新單。
今天的目標就是寫進資料庫,並產生一個簡單的表格來看(最陽春的那種)
主要記錄的有幾個欄位
OrderNo
- 訂單編號Amonut
- 訂單金額PrdtName
- 顧客名稱PayType
- 付款方式ExpireDate
- 訂單逾期日期AutoBilling
- 是否自動請款ExpBillingDays
- 自動請款天數TSNo
- 交易編號Status
- 處理狀態Description
- 回應訊息AtmPayNo
- 虛擬帳號WebAtmURL
- Web ATM 網址OtpURL
- 一次性密碼網址CardPayURL
- 信用卡付款網址之前規劃的欄位已經有了 [訂單編號
, 訂單總金額
, 付款方式
, 訂單狀態
, 訂單過期日期
],
還缺少 [顧客名稱
, 是否自動請款
, 自動請款天數
, 交易編號
, 回應訊息
, 虛擬帳號
, Web ATM 網址
, 一次性密碼網址
, 信用卡付款網址
]
> php artisan make:migration --table=sale_orders update_sale_order
// database/migrations/[current_date_time]_update_sale_order.php
public function up()
{
Schema::table('sale_orders', function (Blueprint $table) {
$table->string('prdt_name', 50)->comment('顧客名稱');
$table->string('auto_billing', 1)->nullable()->comment('是否自動請款');
$table->tinyInteger('exp_billing_days')->nullable()->comment('自動請款天數');
$table->string('ts_no', 20)->nullable(false)->comment('交易編號');
$table->string('description', 50)->nullable()->comment('回應訊息');
$table->string('atm_pay_no', 14)->nullable()->comment('虛擬帳號');
$table->string('web_atm_url', 255)->nullable()->comment('Web ATM 網址');
$table->string('otp_url', 255)->nullable()->comment('一次性密碼網址');
$table->string('card_pay_url', 255)->nullable()->comment('信用卡付款網址');
});
}
/**
* Reverse the migrations.
*
* @return void
*/
public function down()
{
Schema::table('sale_orders', function (Blueprint $table) {
$table->dropColumn(['prdt_name', 'auto_billing', 'exp_billing_days', 'ts_no', 'description', 'atm_pay_no', 'web_atm_url', 'otp_url', 'card_pay_url']);
});
}
// database/migrations/[create_date_time]_create_sale_orders_table.php
...
$table->dateTime('pay_datetime')->nullable()->comment('付款時間');
...
> php artisan migrate:fresh
(此工具為 PhpStorm 的 Database,在開發的時候能檢查SQL語法對應的表格或欄位,非工商 XD)
// app/Models/sale_order.php
protected $fillable = [
...
'prdt_name',
'auto_billing',
'exp_billing_days',
'ts_no',
'description',
'atm_pay_no',
'web_atm_url',
'otp_url',
'card_pay_url'
];
public function create_order(Request $request)
{
$sinopac = $this->initSinopac();
$order_no = date('YmdHis');
$amount = random_int(4000, 10000);
$pay_type = ($request->get('credit', '') === 'Y') ? 'C' : 'A';
$expire_date = date('Ymd', time() + 604800);
$data = [
'ShopNo' => $sinopac->shop_no,
'OrderNo' => $order_no,
'Amount' => $amount . '00',
'CurrencyID' => 'TWD',
'PrdtName' => '大河',
'ReturnURL' => 'http://10.11.22.113:8803/QPay.ApiClient-Sandbox/Store/Return',
'BackendURL' => 'https://sandbox.sinopac.com/funBIZ.ApiClient/AutoPush/PushSuccess',
'PayType' => $pay_type,
'ATMParam' => [
'ExpireDate' => $expire_date,
],
];
$data = $sinopac->requestDataset('OrderCreate', $data);
$message = $sinopac->callApi('https://apisbx.sinopac.com/funBIZ/QPay.WebAPI/api/Order', $data);
$reply_nonce = $message['Nonce'] | '';
if (!$reply_nonce) {
$msg = 'Reply message haven\'t Nonce';
Log::error($msg , $message);
throw new \Exception($msg);
}
// 1. nonce 計算 iv
$iv = $sinopac->calculateIv($reply_nonce);
// 2. 計算 hash_id (AES key)
$hash_id = $sinopac->calcHashId();
// 3. message 解密
$decrypt_message = $sinopac->decryptMessage($message['Message'], $hash_id, $iv);
// 4. 驗證 sign
$sign = $sinopac->generateSign($decrypt_message, $reply_nonce, $hash_id);
if (!($sign === $message['Sign'])) {
return ['msg' => '驗證錯誤,內文簽章不同'];
}
// 這裡的 – 是 \xE2 不是 \x2D
$description = explode(' – ', $decrypt_message['Description']);
if ($description[0] !== 'S0000') {
Log::alert('訂單未建立成功', $decrypt_message);
}
$dataset = [
'customer_id' => 0,
'order_no' => $order_no,
'total' => $amount,
'pay_type' => $pay_type,
'expire_date' => $expire_date,
'ts_no' => $decrypt_message['TSNo'],
'status' => $decrypt_message['Status'],
'description' => $decrypt_message['Description'],
'mailing_address' => '',
'prdt_name' => '大河',
];
if ($pay_type === 'C') {
// 信用卡
$card_param = $decrypt_message['CardParam'];
$dataset = array_merge($dataset, [
'card_pay_url' => $card_param['CardPayURL'],
]);
} else {
// 虛擬帳號
$atm_param = $decrypt_message['ATMParam'];
$dataset = array_merge($dataset, [
'atm_pay_no' => $atm_param['AtmPayNo'],
'web_atm_url' => $atm_param['WebAtmURL'],
'otp_url' => $atm_param['OtpURL'],
]);
}
$id = sale_order::create($dataset)->id;
return [
'dataset' => $dataset,
'id' => $id
];
}
> php .\artisan make:controller Web
// app/Http/Controllers/Web.php
public function orders()
{
return view('orders', [
'dataset' => sale_order::all()->toArray()
]);
}
resources/views
建立 orders.blade.php
// resources/views/orders.blade.php
<style>
table {
width: 100%;
text-align: center;
}
thead > tr, tr:hover {
background: #1a202c30;
}
</style>
<table>
<thead>
<tr>
<th>#</th>
<th>訂單編號</th>
<th>訂單金額</th>
<th>訂單類型</th>
<th>客戶名稱</th>
<th>客戶住址</th>
<th>處理狀態</th>
<th>銀行回覆內容</th>
<th>付款期限</th>
<th>建立日期</th>
<th>更新日期</th>
</tr>
</thead>
<tbody>
@foreach($dataset as $index => $line)
<tr>
<td>{{ $index + 1 }}</td>
<td>{{ $line['order_no'] }}</td>
<td>{{ $line['total'] }}</td>
<td>{{ $line['pay_type'] }}</td>
<td>{{ $line['prdt_name'] }}</td>
<td>{{ $line['mailing_address'] }}</td>
<td>{{ $line['status'] }}</td>
<td>{{ $line['description'] }}</td>
<td>{{ $line['expire_date'] }}</td>
<td>{{ $line['created_at'] }}</td>
<td>{{ $line['updated_at'] }}</td>
</tr>
@endforeach
</tbody>
</table>
// routes/web.php
Route::get('/orders', [Web::class, 'orders']);
OK~來看個成果
差點趕不上發文阿,要改的bug好多阿,有點懷疑自己為什麼要參賽了
明天要把讓自己輕鬆一些,簡單看一下回應的網頁長怎麼樣好了 ('web_atm_url', 'otp_url', 'card_pay_url')